////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_BENAPHORE_H__
#define __WN_BENAPHORE_H__

#include "WNCore/inc/WNBase.h"
#include "WNConcurrency/inc/WNSemaphore.h"

typedef struct {
    WN_ATOM_T mCounter;
    WN_SEMAPHORE_T mSemaphore;
} WN_BENAPHORE_T;

__WN_INLINE WN_VOID WNBenaphoreInitialize(WN_BENAPHORE_T* _benaphore);
__WN_INLINE WN_VOID WNBenaphoreDestroy(WN_BENAPHORE_T* _benaphore);
__WN_INLINE WN_VOID WNBenaphoreLock(WN_BENAPHORE_T* _benaphore);
__WN_INLINE WN_BOOL WNBenaphoreTryLock(WN_BENAPHORE_T* _benaphore);
__WN_INLINE WN_VOID WNBenaphoreUnlock(WN_BENAPHORE_T* _benaphore);

#ifdef _WN_CPLUSPLUS
    class WNBenaphoreScopeLock;

    class WNBenaphore {
    public:
        __WN_INLINE WNBenaphore();
        __WN_INLINE ~WNBenaphore();

        __WN_INLINE WN_VOID Lock();
        __WN_INLINE WN_BOOL TryLock();
        __WN_INLINE WN_VOID Unlock();

    private:
        friend class WNBenaphoreScopeLock;

    private:
        WN_BENAPHORE_T mBenaphore;
    };

    class WNBenaphoreScopeLock {
    public:
        __WN_INLINE WNBenaphoreScopeLock(WN_BENAPHORE_T* _benaphore);
        __WN_INLINE WNBenaphoreScopeLock(WNBenaphore& _benaphore);
        __WN_INLINE ~WNBenaphoreScopeLock();

    private:
        WNBenaphoreScopeLock() {}

    private:
        WN_BENAPHORE_T* mBenaphore;
    };

    #define WN_BENAPHORE_SCOPE_LOCK(_benaphore) WNBenaphoreScopeLock lock__LINE_____COUNTER__(_benaphore)
#endif

#include "WNConcurrency/inc/WNBenaphore.inl"

#endif // __WN_BENAPHORE_H__